from random import randint
from elementtree.ElementTree import parse
from math import ceil

pilot = {'atk':2, 'def':2, 'ew':1, 'ld':0}

class Weapon:
   def __init__(self, name, code, dm, acc, maxRange, rof, melee, indirect, thrown, ae, ai, arc, notes):
      self.name = name
      self.code = code
      self.dm = dm
      self.acc = acc
      if melee:
         self.rng = maxRange,
      elif thrown:
         self.rng = maxRange / 2, maxRange
      else:
         self.rng = int(ceil(int(maxRange)/16.0)), int(maxRange)/8, int(maxRange)/4, int(maxRange)/2, int(maxRange)
      self.rof = rof
      self.melee = melee
      self.indirect = indirect
      self.thrown = thrown
      self.ae = ae
      self.ai = ai
      self.arc = arc
      self.notes = notes

   def getRangeband(self, distance):
      """Returns which rangeband the weapon is in at distance. 0 is out of range. 1 is pb, 2 is short, and so on."""
      rangeband = 0
      if not distance > self.rng[-1]:
         rangeband += 1
         for i in self.rng:
            if distance > i:
               rangeband += 1
      return rangeband

   def getRangeMod(self, rangeband):
      """Returns the range modifiers for a given rangeband with the weapon. Includes weapon acc"""
      if rangeband == 0:
         rangeMod = -10
      else:
         if self.melee:
            rangeMod = 0
         elif self.thrown:
            if rangeband == 1:
               rangeMod = 0
            else:
               rangeMod = -1
         else:
            if rangeband == 1:
               if self.notes.has_key('mr'):
                  rangeMod = -10
               else:
                  rangeMod = 1
            elif rangeband == 2:
               if self.notes.has_key('mr'):
                  rangeMod = -1
               else:
                  rangeMod = 0
            elif rangeband == 3:
               rangeMod = -1
            elif rangeband == 4:
               if self.notes.has_key('snp'):
                  rangeMod = 0
               else:
                  rangeMod = -2
            else:
               if self.notes.has_key('snp'):
                  rangeMod = -1
               else:
                  rangeMod = -3
      return rangeMod + self.acc

class Gear:
   def __init__(self, name, pilot):
      tree = parse('gearList.xml')
      elem = tree.getroot()
      for i in elem:
         if i.attrib['name'] == name:
            gear = i
            break

      tree = parse('chassisList.xml')
      elem = tree.getroot()
      for i in elem:
         if i.attrib['name'] == gear.attrib['chassis']:
            chassis = i
            break 

      for value in chassis.attrib:
         if value == 'chassis':
            self.chassis = chassis.attrib[value]
         elif value == 'sensors':
            self.sensors = int(chassis.attrib[value])
         elif value == 'detect':
            self.detect = int(chassis.attrib[value])
         elif value == 'comm':
            self.comm = int(chassis.attrib[value])
         elif value == 'autocomm':
            self.autocomm = int(chassis.attrib[value])
         elif value == 'actions':
            self.actions = int(chassis.attrib[value])
         elif value == 'armor':
            self.armor = int(chassis.attrib[value])
         elif value == 'size':
            self.size = int(chassis.attrib[value])
         elif value == 'fc':
            self.fc = int(chassis.attrib[value])
         elif value == 'man':
            self.man = int(chassis.attrib[value])
         
      for value in gear.attrib: # Overrides the generic chassis data with gear specific data
         if value == 'name':
            self.name = gear.attrib[value]
         elif value == 'sensors':
            self.sensors = int(gear.attrib[value])
         elif value == 'detect':
            self.detect = int(gear.attrib[value])
         elif value == 'comm':
            self.comm = int(gear.attrib[value])
         elif value == 'autocomm':
            self.autocomm = int(gear.attrib[value])
         elif value == 'actions':
            self.actions = int(gear.attrib[value])
         elif value == 'armor':
            self.armor = int(gear.attrib[value])
         elif value == 'size':
            self.size = int(gear.attrib[value])
         elif value == 'fc':
            self.fc = int(gear.attrib[value])
         elif value == 'man':
            self.man = int(gear.attrib[value])

      self.movement = {}
      move = chassis.find('movements').getchildren()
      for i in move:
        self.movement[i.attrib['type']] = int(i.attrib['speed'])
      if gear.find('movements'):
         move = gear.find('movements').getchildren()
         for i in move:
            self.movement[i.attrib['type']] = int(i.attrib['speed'])
      
      self.perks = {}
      perk = chassis.find('perks').getchildren()
      for i in perk:
         self.perks[i.attrib['type']] = int(i.attrib['value'])
      if gear.find('perks'):
         perk = gear.find('perks').getchildren()
         for i in perk:
            self.perks[i.attrib['type']] = int(i.attrib['value'])
      markedForDel = {}
      for i in self.perks: # Cleans up the perks list
         if self.perks[i] == 0:
            markedForDel[i] = 1
      for i in markedForDel:
         self.perks.pop(i)

      self.weapons = {}
      
      weapons = gear.find('defaultWeapons').getchildren()
      for weapon in weapons:
         self.addWeapon(weapon.attrib['code'])

         for value in weapon.attrib: # This overrides the default weapon values with gear specific ones.
            if value == 'rof':
               self.weapons[weapon.attrib['code']].rof = int(weapon.attrib[value])
            elif value == 'arc':
               self.weapons[weapon.attrib['code']].arc = weapon.attrib[value]
            else:
               try:
                  self.weapons[weapon.attrib['code']].notes[value] = int(weapon.attrib[value])
               except:
                  pass
      self.addWeapon('physical')

      self.pilot = pilot

      self.ca = {}
      self.ca['damage'] = 0
      self.ca['speedband'] = 1 # -1 is reverse, 0 is stationary, 1 is combat, 2 is top.
      for i in self.movement:
         self.ca['movementMode'] = i
         break
      self.ca['armor'] = self.armor
      self.ca['stunned'] = 0
      return

   def getAttackMod(self):
      """Returns ranged attack modifier based on speed and fire control"""
      rangeMod = 0
      if self.ca['speedband'] == 0:
         rangeMod += 2
      elif self.ca['speedband'] == 2:
         rangeMod -= 3
      return rangeMod + self.fc

   def getBoxes(self):
      """Total number of danage "boxes" a gear has left"""
      boxes = 4
      if self.perks.has_key('sturdy'):
         boxes += self.perks['sturdy']
      if self.perks.has_key('field armor'):
         boxes += self.perks['field armor']
      if self.perks.has_key('fragile'):
         boxes -= self.perks['fragile']
      return boxes - self.ca['damage']
   
   def isDead(self):
      """Is the unit dead?"""
      if self.getBoxes() <= 0:
         return 1

   def getPenelty(self):
      """Returns the modifier for damage"""
      penelty = 0
      boxes = self.getBoxes()
      if self.perks.has_key('fragile'):
         if boxes == 1:
            penelty = -1
      else:
         if boxes == 1:
            penelty = -2
         elif boxes == 2:
            penelty = -1
      return penelty
              
   def getDodge(self):
      """Returns the modifier for speed based on the Gear's current movement mode. Include maneuver ."""
      if self.ca['speedband'] == 0:
         dodge = -3
      else:
         speed = self.movement[self.ca['movementMode']]
         if self.ca['speedband'] == 1:
            speed = int(ceil(speed/2.0))
         if speed < 3:
            dodge = -2
         elif speed < 5:
            dodge = -1
         elif speed < 7:
            dodge = 0
         elif speed < 10:
            dodge = 1
         else:
            dodge = 2
      return dodge + self.man

   def addWeapon(self, code):
      tree = parse('weaponList.xml')
      elem = tree.getroot()
      
      for values in elem:
         if values.attrib['code'] == code:
            # Setting some default values that may not be included in the XML.
            if self.weapons.has_key(code):
               self.weapons[code].notes['count'] = 2
               if self.weapons[code].notes.has_key('ammo'):
                  self.weapons[code].notes['ammo'] *= 2                        
            else:                                      
               arc = 'f'
               acc = 0
               rof = 0
               ae = 0
               melee = 0
               indirect = 0
               thrown = 0
               ai = 0
               notes = {}
               for value in values.attrib:
                  if value == 'name':
                     name = values.attrib[value]
                  elif value == 'ae':
                     ae = int(values.attrib[value])
                  elif value == 'ai':
                     ai = int(values.attrib[value])
                  elif value == 'm':
                     melee = int(values.attrib[value])
                  elif value == 'rof':
                     rof = int(values.attrib[value])
                  elif value == 'if':
                     indirect = int(values.attrib[value])
                  elif value == 't':
                     thrown = int(values.attrib[value])
                  elif value == 'acc':
                     acc = int(values.attrib[value])
                  elif value == 'range':
                     if values.attrib[value] == 't':
                        maxRange = self.size * 2
                     else:
                        maxRange = int(values.attrib[value])
                  elif value == 'dm':
                     if values.attrib[value].find('size') > -1:
                        if values.attrib[value].find('+') > -1:
                           dm = self.size + int(values.attrib[value].split('+')[1])
                        else:
                           dm = self.size
                     else:
                        dm = int(values.attrib[value])
                  else:
                     try:
                        notes[value] = int(values.attrib[value])
                     except:
                        pass
               self.weapons[code] = Weapon(name, code, dm, acc, maxRange, rof, melee, indirect, thrown, ae, ai, arc, notes)
                                           
   def removeWeapon(self, code):
      self.weapons.pop(code)
